package burubaka.common;

import java.io.IOException;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.slim3.util.StringUtil;
import org.slim3.util.TimeZoneLocator;

import burubaka.BurubakaConstants;
import burubaka.model.PayOff;
import burubaka.model.RaceInfo;

import com.google.appengine.api.urlfetch.HTTPMethod;

/**
 * @author tk
 * 
 */
public class NetkeibaUtil {

	private final static SimpleDateFormat SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm");
	static {
		SDF.setTimeZone(TimeZoneLocator.get());
	}

	/**
	 * トップページのソースを取得します。
	 * 
	 * @return 本文
	 * @throws MalformedURLException
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public static String getTopPageStr() throws MalformedURLException, IOException, InterruptedException {
		return BurubakaUtil.getURLText(BurubakaConstants.URL_NET_KEIBA_GOM, HTTPMethod.POST,
				BurubakaConstants.ENCODE_EUC);
	}

	/**
	 * トップページのレース名一覧を取得します。
	 * 
	 * @param text
	 * @return receNmae
	 */
	public static String getTopPageRaceNameArea(String text) {
		return BurubakaUtil.substring("<ul class=\"month_race_list\">", "</ul>", text);
	}

	/**
	 * 対象レースのURLを取得します。
	 * 
	 * @param racename
	 * @param text
	 * @return receUrl
	 */
	public static String getRaceUrl(String racename, String text) {

		if (racename == null) {
			return null;
		}

		int i = 0;

		List<String> hrefL = BurubakaUtil.substringList("<a href=\"", "\"", text);
		List<String> raceNameL = BurubakaUtil.substringList("title=\"", "\"", text);

		for (String name : raceNameL) {
			if (name.indexOf(racename) >= 0) {
				String urlParam = hrefL.get(i);
				return BurubakaConstants.URL_NET_KEIBA_GOM + urlParam;
			}
			i++;
			continue;
		}

		return null;
	}

	/**
	 * レース情報を取得する
	 * 
	 * @param text
	 * @param url
	 * @return RaceInfo
	 * @throws Exception
	 */
	public static RaceInfo getRaceInfo(String text, String url) throws Exception {

		RaceInfo raceInfo = new RaceInfo();
		raceInfo.setRaceNo(getRaceId(url));
		raceInfo.setRaceURL(url);

		String contentsTitle = getContentsTitle(text);
		String[] heads = contentsTitle.split(" ");
		if (heads == null || heads.length < 4) {
			return null;
		}
		String raceDate = heads[0].replaceAll("年", "/").replaceAll("月", "/").replaceAll("日", "");
		raceInfo.setRaceDate(raceDate);
		raceInfo.setStartTime(SDF.parse(raceDate + " 00:00:00"));
		String raceName = heads[2].trim();
		raceInfo.setRaceName(raceName);
		raceInfo.setRaceInfo1(getRaceConditionStr(text));
		raceInfo.setRaceInfo2(heads[3].trim());
		raceInfo.setRaceInfo3(heads[0].trim());

		return raceInfo;
	}

	/**
	 * 
	 * @param text
	 * @return
	 */
	private static String getContentsTitle(String text) {
		String contents = BurubakaUtil.substring("<div class=\"contents_title\">", "</div>", text);
		if (StringUtil.isEmpty(contents)) {
			return "";
		}
		String title = BurubakaUtil.substring("<span>", "</span>", contents);
		if (StringUtil.isEmpty(title)) {
			return "";
		}
		return title;
	}

	/**
	 * 
	 * @param text
	 * @return
	 */
	private static String getRaceConditionStr(String text) {
		return BurubakaUtil.substring("<p class=\"race_condition\">", "<br />", text);
	}

	/**
	 * 着順取得
	 * 
	 * @param text
	 * @return
	 */
	public static String getFinishPoint(String text) {
		return BurubakaUtil.substring("<td class=\"rank\" nowrap=\"nowrap\">", "</td>", text);
	}

	/**
	 * 騎手aタグつき取得
	 * 
	 * @param text
	 * @return
	 */
	public static String getJockeyA(String text) {
		return BurubakaUtil.substring("<td class=\"align_left\">", "</td>", text);
	}

	/**
	 * 馬名aタグつき取得
	 * 
	 * @param text
	 * @return
	 */
	public static String getHorseNameA(String text) {
		String ret = BurubakaUtil.substring("<td  class=\"align_left\" nowrap>", "</td>", text);
		if (ret != null) {
			return ret;
		}
		return BurubakaUtil.substring("<td class=\"align_left\" nowrap=\"nowrap\">", "</td>", text);
	}

	/**
	 * 馬情報取得
	 * 
	 * @param text
	 * @return
	 */
	public static ArrayList<String> getHorseInfo(String text) {
		return BurubakaUtil.substringList("<td nowrap=\"nowrap\">", "</td>", text);
	}

	/**
	 * 枠番取得
	 * 
	 * @param text
	 * @return
	 */
	public static String getWakuNo(String text) {
		return BurubakaUtil.substring("<td class=\"waku", "\"", text);
	}

	/**
	 * 馬情報エリア取得
	 * 
	 * @param text
	 * @return
	 */
	public static List<String> getHorseInfoAreaList(String text) {
		String dataTbl = BurubakaUtil.substring("<table class=\"race_card_table\" summary=", "</table>", text);
		if (dataTbl == null) {
			return null;
		}
		List<String> trList = BurubakaUtil.substringList("<tbody>", "</tbody>", dataTbl);
		if (trList.size() > 1) {
			return trList;
		}

		String tbody = BurubakaUtil.substring("<tbody>", "</tbody>", dataTbl);
		if (tbody == null) {
			return null;
		}

		tbody = tbody.replace("</td><tr>", "</td></tr><tr>");
		return BurubakaUtil.substringList("<tr>", "</tr>", tbody);
	}

	/**
	 * レースID取得
	 * 
	 * @param url
	 * @return raceNo
	 * @throws Exception
	 */
	public static String getRaceId(String url) throws Exception {
		String raceNo = BurubakaUtil.substring("&rid=", "&", url);
		if (raceNo != null) {
			return raceNo;
		}
		raceNo = BurubakaUtil.substring("&rid=", "", url);
		if (raceNo != null) {
			return raceNo;
		}
		return "";
	}

	/**
	 * 結果URLテキストを取得する
	 * 
	 * @param raceInfo
	 * @return URLText
	 * @throws Exception
	 */
	public static String getResultURLText(RaceInfo raceInfo) throws Exception {
		return getURLText(raceInfo.getRaceURL(), BurubakaConstants.BASE_URL_RESULT_LOCAL);
	}

	/**
	 * URLテキストを取得する
	 * 
	 * @param url
	 * @param BASE_URL
	 * @return URLText
	 * @throws Exception
	 */
	public static String getURLText(String url, String baseUrl) throws Exception {
		String raceId = getRaceId(url);
		if (StringUtil.isEmpty(raceId)) {
			return "";
		}

		String goUrl = baseUrl.replace("*", raceId);
		return getURLText(goUrl);
	}

	/**
	 * URLテキストを取得する
	 * 
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public static String getURLText(String url) throws Exception {
		return BurubakaUtil.getURLText(url, HTTPMethod.POST, BurubakaConstants.ENCODE_EUC);
	}

	/**
	 * 開始日付を取得する
	 * 
	 * @param text
	 * @param url
	 * @return RaceInfo
	 * @throws Exception
	 */
	public static Date getStartDate(String text) throws Exception {
		// レース情報取得
		String contentsTitle = getContentsTitle(text);
		String[] heads = contentsTitle.split(" ");
		if (heads == null || heads.length < 4) {
			return null;
		}
		String yMd = heads[0].replaceAll("年", "/").replaceAll("月", "/").replaceAll("日", "");

		String condition = getRaceConditionStr(text);
		if (StringUtil.isEmpty(condition)) {
			return null;
		}

		String hm = BurubakaUtil.substring("発走：", "", condition.trim());
		return SDF.parse(yMd + " " + hm);
	}

	/**
	 * 締切り日を取得する
	 * 
	 * @param text
	 * @param url
	 * @return RaceInfo
	 * @throws Exception
	 */
	public static Date getDeadline(String text) throws Exception {
		return BurubakaUtil.getDeadline(getStartDate(text));
	}

	private static String getPayoffNo(String no) {
		return no.replaceAll(" ", "").replace("→", "-");
	}

	/**
	 * 配当情報を取得する
	 * 
	 * @param text
	 * @return 配当情報
	 */
	public static PayOff getPayOff(String text) {
		PayOff ret = new PayOff();

		List<String> dataTbls = BurubakaUtil.substringList("<table summary=\"払戻\">", "</table>", text);
		String data1 = dataTbls.get(0).replace("\n", "").replace("<br></tr>", "<br></td></tr>")
				.replace("<br><td", "<br></td><td").replaceAll("<br>", "");
		ArrayList<String> payInfo1List = BurubakaUtil.substringList("<tr>", "</tr>", data1);
		for (String payInfo : payInfo1List) {
			// 単勝
			setWin(ret, payInfo);
			// 複勝
			setPlace(ret, payInfo);
			// 枠連
			setBracketQuinella(ret, payInfo);
			// 馬複
			setQuinella(ret, payInfo);
		}

		String data2 = dataTbls.get(1).replace("\n", "").replace("<br></tr>", "<br></td></tr>")
				.replace("<br><td", "<br></td><td").replaceAll("<br>", "");

		ArrayList<String> payInfo2List = BurubakaUtil.substringList("<tr>", "</tr>", data2);
		for (String payInfo : payInfo2List) {
			// ワイド
			setQuinellaPlace(ret, payInfo);
			// 枠単
			setBracketExacta(ret, payInfo);
			// 馬単
			setExacta(ret, payInfo);
			// 3連複
			setTrio(ret, payInfo);
			// 3連単
			setTrifecta(ret, payInfo);
		}

		return ret;
	}

	/**
	 * 単勝設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setWin(PayOff payOff, String payInfo) {
		String tan = BurubakaUtil.substring("<td class=\"tan\">", "</td>", payInfo);
		if (StringUtil.isEmpty(tan)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);
		payOff.setWinNo(getPayoffNo(kekka));
		payOff.setWin(BurubakaUtil.parserLongHaitou(haitou));
	}

	/**
	 * 複勝設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setPlace(PayOff payOff, String payInfo) {
		String fuku = BurubakaUtil.substring("<td class=\"fuku\">", "</td>", payInfo);
		if (StringUtil.isEmpty(fuku)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);
		String[] plcNos = getPayoffNo(kekka).split("<br/>");
		String[] plcs = getPayoffNo(haitou).split("<br/>");
		payOff.setPlace1No(plcNos[0]);
		payOff.setPlace1(BurubakaUtil.parserLongHaitou(plcs[0]));
		payOff.setPlace2No(plcNos[1]);
		payOff.setPlace2(BurubakaUtil.parserLongHaitou(plcs[1]));
		payOff.setPlace3No(plcNos[2]);
		payOff.setPlace3(BurubakaUtil.parserLongHaitou(plcs[2]));
	}

	/**
	 * 枠連設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setBracketQuinella(PayOff payOff, String payInfo) {
		String waku = BurubakaUtil.substring("<td class=\"waku\">", "</td>", payInfo);
		if (StringUtil.isEmpty(waku)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);
		payOff.setBracketQuinellaNo(getPayoffNo(kekka));
		payOff.setBracketQuinella(BurubakaUtil.parserLongHaitou(haitou));
	}

	/**
	 * 馬連設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setQuinella(PayOff payOff, String payInfo) {

		String uren = BurubakaUtil.substring("<td class=\"uren\">", "</td>", payInfo);
		if (StringUtil.isEmpty(uren)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);

		payOff.setQuinellaNo(getPayoffNo(kekka));
		payOff.setQuinella(BurubakaUtil.parserLongHaitou(haitou));
	}

	/**
	 * ワイド設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setQuinellaPlace(PayOff payOff, String payInfo) {
		String wide = BurubakaUtil.substring("<td class=\"wide\">", "</td>", payInfo);
		if (StringUtil.isEmpty(wide)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);

		String[] qpNos = getPayoffNo(kekka).split("<br/>");
		String[] qps = getPayoffNo(haitou).split("<br/>");
		payOff.setQuinellaPlace1No(qpNos[0]);
		payOff.setQuinellaPlace1(BurubakaUtil.parserLongHaitou(qps[0]));
		payOff.setQuinellaPlace2No(qpNos[1]);
		payOff.setQuinellaPlace2(BurubakaUtil.parserLongHaitou(qps[1]));
		payOff.setQuinellaPlace3No(qpNos[2]);
		payOff.setQuinellaPlace3(BurubakaUtil.parserLongHaitou(qps[2]));
	}

	/**
	 * 枠単設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setBracketExacta(PayOff payOff, String payInfo) {
		String waku = BurubakaUtil.substring("<td class=\"waku\">", "</td>", payInfo);
		if (StringUtil.isEmpty(waku)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);

		payOff.setBracketExactaNo(getPayoffNo(kekka));
		payOff.setBracketExacta(BurubakaUtil.parserLongHaitou(haitou));
	}

	/**
	 * 馬単設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setExacta(PayOff payOff, String payInfo) {
		String utan = BurubakaUtil.substring("<td class=\"utan\">", "</td>", payInfo);
		if (StringUtil.isEmpty(utan)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);

		payOff.setExactaNo(getPayoffNo(kekka));
		payOff.setExacta(BurubakaUtil.parserLongHaitou(haitou));
	}

	/**
	 * ３連複設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setTrio(PayOff payOff, String payInfo) {
		String sanfuku = BurubakaUtil.substring("<td class=\"sanfuku\">", "</td>", payInfo);
		if (StringUtil.isEmpty(sanfuku)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);

		payOff.setTrioNo(getPayoffNo(kekka));
		payOff.setTrio(BurubakaUtil.parserLongHaitou(haitou));
	}

	/**
	 * ３連単設定
	 * 
	 * @param payOff
	 * @param payInfo
	 */
	private static void setTrifecta(PayOff payOff, String payInfo) {
		String santan = BurubakaUtil.substring("<td class=\"santan\">", "</td>", payInfo);
		if (StringUtil.isEmpty(santan)) {
			return;
		}
		String kekka = getKekka(payInfo);
		String haitou = getHaitou(payInfo);

		payOff.setTrifectaNo(getPayoffNo(kekka));
		payOff.setTrifecta(BurubakaUtil.parserLongHaitou(haitou));
	}

	/**
	 * 配当取得
	 * 
	 * @param payInfo
	 * @return
	 */
	private static String getHaitou(String payInfo) {
		return BurubakaUtil.substring("<td class=\"dividend\" nowrap=\"nowrap\">", "</td>", payInfo);
	}

	/**
	 * 結果取得
	 * 
	 * @param payInfo
	 * @return
	 */
	private static String getKekka(String payInfo) {
		return BurubakaUtil.substring("<td>", "</td>", payInfo);
	}

}
